﻿using AvaVSExt.Attributes;
using AvaVSExt.Helpers;
using AvaVSExt.Xaml;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AvaVSExt
{

    public partial class Program
    {
        [VSCommand("exmod")]
        public static void RunExtractModule()
        {

            var info = VSHelper.GetSelectionItemInfo();

            var file = info.ItemFullPath;

            if (file.EndsWith("xaml") == false) return;

            var text = File.ReadAllText(file);
            if (string.IsNullOrWhiteSpace(text)) return;
            var selectionText = info.SelectionText;

            var isValidBlock = XmlHelper.IsValidBlock(selectionText);

            if (isValidBlock == false)
            {
                MessageBox.Show("當前xml段不完整或者不合法！");
                return;
            }

            if (InputBoxHelper.Show("请输入文件名", "请输入文件名", "NewView", out var componentName))
            {
                var xamlInfo = XamlInfo.Parse(text);

                //var processedhostCode = ExtractModule.GetProcessedHostCode(text, selectionStartIndex, selectionEndIndex);
                var processedXamlPartCode = ExtractModule.GetProcessedXamlPartCode(text, xamlInfo, selectionText, componentName);
                var processedCodePartCode = ExtractModule.GetProcessedCodePartCode(xamlInfo, componentName);

                var xamlPath = ExtractModule.GetXamlPath(file, componentName);
                var codePath = ExtractModule.GetCodePath(file, componentName);

                //File.WriteAllText(file, processedhostCode);

                var localNamespaceName = xamlInfo.GetNamespaceFromClassName();
                var localNamespaceShortName = Xmlns.GetNamespaceShortName(localNamespaceName);


                info.UpdateSelection($"<{localNamespaceShortName}:{componentName}/>");
                File.WriteAllText(xamlPath, processedXamlPartCode);
                File.WriteAllText(codePath, processedCodePartCode);

                VSHelper.Open(xamlPath);
            }

        }
    }

    /// <summary>
    /// 提取模塊。
    /// </summary>
    public class ExtractModule
    {
        public static string GetCodePath(string hostFile, string componentName)
        {
            var dir = Path.GetDirectoryName(hostFile);
            var fileName = string.Empty;
            if (hostFile.EndsWith(".axaml")) fileName = componentName + ".axaml.cs";
            else if (hostFile.EndsWith(".xaml")) fileName = componentName + ".xaml.cs";
            else throw new Exception();

            return Path.Combine(dir, fileName);
        }
        public static string GetXamlPath(string hostFile, string componentName)
        {
            var dir = Path.GetDirectoryName(hostFile);
            var fileName = string.Empty;
            if (hostFile.EndsWith(".axaml")) fileName = componentName + ".axaml";
            else if (hostFile.EndsWith(".xaml")) fileName = componentName + ".xaml";
            else throw new Exception();

            return Path.Combine(dir, fileName);
        }

        public static string GetProcessedHostCode(string hostCode, int selectionStartIndex, int selectionEndIndex)
        {
            var part1 = hostCode.Substring(0, selectionEndIndex);
            var part2 = hostCode.Substring(selectionEndIndex + 1);

            return part1 + part2;
        }

        public static string GetProcessedXamlPartCode(string hostCode, XamlInfo xamlInfo, string selectionText, string componentName)
        {
            var sb = new StringBuilder();
            var localNamespaceName = xamlInfo.GetNamespaceFromClassName();

            sb.AppendLine($@"<UserControl
    x:Class=""{localNamespaceName}.{componentName}""
    xmlns=""https://github.com/avaloniaui""
    xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
    xmlns:d=""http://schemas.microsoft.com/expression/blend/2008""
    xmlns:mc=""http://schemas.openxmlformats.org/markup-compatibility/2006""");

            foreach (var namespaceUsing in xamlInfo.Namespaces)
            {
                sb.AppendLine(namespaceUsing.ToString());
            }

            var localNamespaceShortName = Xmlns.GetNamespaceShortName(localNamespaceName);

            if (xamlInfo.Namespaces.Any(i => i.ShortName == localNamespaceShortName) == false)
            {
                sb.AppendLine(new UsingPair() { NamespaceName = localNamespaceName, ShortName = localNamespaceShortName }.ToString());
            }

            sb.AppendLine(@"    d:DesignHeight=""450""
    d:DesignWidth=""800""");

            if (string.IsNullOrWhiteSpace(xamlInfo.DataType) == false)
                sb.AppendLine($@"    x:DataType=""{xamlInfo.DataType}""");

            sb.AppendLine(@"    mc:Ignorable=""d"">");

            sb.AppendLine();

            sb.AppendLine(selectionText);

            sb.AppendLine();

            sb.AppendLine(@"</UserControl>");

            return sb.ToString();
        }

        public static string GetProcessedCodePartCode(XamlInfo xamlInfo, string componentName)
        {
            var localNamespaceName = xamlInfo.GetNamespaceFromClassName();

            var code = $@"using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace {localNamespaceName};

public partial class {componentName} : UserControl
{{
    public {componentName}()
    {{
        InitializeComponent();
    }}
}}";
            return code;
        }
    }
}
